﻿using System.Security.Cryptography;
using System.Text;

namespace Lib.Security;
/// <summary>
/// RSA加密解密及RSA签名和验证
/// </summary>
public class RSA {
    /// <summary>
    /// 生成 RSA 密钥, 返回 0.私钥、1.公钥
    /// </summary>
    public static string[] Key {
        get {
            try {
                var Res = System.Security.Cryptography.RSA.Create();
                return [
                        Res.ToXmlString(true), Res.ToXmlString(false)
                    ];
            } catch {
                throw;
            }
        }
    }
    /// <summary>
    /// 生成包含 RSA 密钥（公钥、私钥）的加解密实体类
    /// </summary>
    public static RSAEntity Entity {
        get {
            try {
                var Res = System.Security.Cryptography.RSA.Create();
                return RSAEntity.Create(Res.ToXmlString(false), Res.ToXmlString(true));
            } catch {
                throw;
            }
        }
    }
    /// <summary>
    /// RSA的加密函数（公钥加密，私钥解密）
    /// </summary>
    /// <param name="PublicKey">公钥</param>
    /// <param name="Value">待加密的数据</param>
    /// <returns>RSA公钥加密后的数据</returns>
    public static string Encrypt(string PublicKey, string Value) {
        try {
            return Encrypt(PublicKey, Encoding.UTF8.GetBytes(Value));
        } catch {
            throw;
        }
    }
    /// <summary>
    /// RSA的加密函数（公钥加密，私钥解密）
    /// </summary>
    /// <param name="PublicKey">公钥</param>
    /// <param name="Value">待加密的数据（字节数组）</param>
    /// <returns>RSA公钥加密后的数据</returns>
    public static string Encrypt(string PublicKey, byte[] Value) {
        try {
            var Res = System.Security.Cryptography.RSA.Create();
            Res.FromXmlString(PublicKey);
            return Convert.ToBase64String(Res.Encrypt(Value, RSAEncryptionPadding.Pkcs1));
        } catch {
            throw;
        }
    }
    /// <summary>
    /// RSA的解密函数（公钥加密，私钥解密）
    /// </summary>
    /// <param name="PrivateKey">私钥</param>
    /// <param name="Value">待解密的数据</param>
    /// <returns>RSA私钥解密后的数据</returns>
    public static string Decrypt(string PrivateKey, string Value) {
        try {
            return Decrypt(PrivateKey, Convert.FromBase64String(Value));
        } catch {
            throw;
        }
    }
    /// <summary>
    /// RSA的解密函数（公钥加密，私钥解密） 
    /// </summary>
    /// <param name="PrivateKey">私钥</param>
    /// <param name="Value">待解密的数据（字节数组）</param>
    /// <returns>RSA私钥解密后的数据</returns>
    public static string Decrypt(string PrivateKey, byte[] Value) {
        try {
            var Res = System.Security.Cryptography.RSA.Create();
            Res.FromXmlString(PrivateKey);
            return Encoding.UTF8.GetString(Res.Decrypt(Value, RSAEncryptionPadding.Pkcs1));
        } catch {
            throw;
        }
    }
    /// <summary>
    /// RSA的签名函数（私钥数字签名，公钥验证）
    /// </summary>
    /// <param name="PrivateKey">私钥</param>
    /// <param name="Sign">待签名的数据</param>
    /// <param name="Code">签名加密方式：MD5、SHA1、SHA256、SHA384、SHA512等</param>
    /// <returns>签名后的数据</returns>
    public static string Signature(string PrivateKey, string Sign, AlgorithType Code = AlgorithType.MD5) {
        try {
            var Res = System.Security.Cryptography.RSA.Create();
            Res.FromXmlString(PrivateKey);
            var Formatter = new RSAPKCS1SignatureFormatter(Res);
            Formatter.SetHashAlgorithm(Code.ToString());
            var SignBytes = Encoding.UTF8.GetBytes(Sign);
            var Bytes = Formatter.CreateSignature(Password.SHA(SignBytes,Code));
            return Convert.ToBase64String(Bytes);
        } catch {

        }
        return null;
    }
    /// <summary>
    /// RSA的签名验证函数（私钥数字签名，公钥验证）
    /// </summary>
    /// <param name="PublicKey">公钥</param>
    /// <param name="Sign">待签名的数据</param>
    /// <param name="Signature">签名后的数据</param>
    /// <param name="Code">签名加密方式：MD5、SHA1、SHA256、SHA384、SHA512</param>
    public static bool Validation(string PublicKey, string Sign, string Signature, AlgorithType Code = AlgorithType.MD5) {
        try {
            var Res = System.Security.Cryptography.RSA.Create();
            Res.FromXmlString(PublicKey);
            var Deformatter = new RSAPKCS1SignatureDeformatter(Res);
            Deformatter.SetHashAlgorithm(Code.ToString());
            var SignBytes = Encoding.UTF8.GetBytes(Sign);
            if (Deformatter.VerifySignature(Password.SHA(SignBytes, Code), Convert.FromBase64String(Signature))) {
                return true;
            }
        } catch {

        }
        return false;
    }
}


